package util

import (
	"fmt"
	"math"
	"reflect"
	"strconv"
	"strings"

	"github.com/bwmarrin/snowflake"
)

// 雪花算法生成的递增唯一id
func SnowflakeId() (uint64, error) {
	node, err := snowflake.NewNode(1)
	if err != nil {
		return 0, err
	}
	id := node.Generate()
	return uint64(id.Int64()), nil
}

// 将不同类型的值转换为 int8 类型
func ToInt8(value interface{}) (int8, error) {
	v := reflect.ValueOf(value)
	if !v.IsValid() {
		return 0, nil
	}

	switch v.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		val := v.Int()
		if val < math.MinInt8 || val > math.MaxInt8 {
			return 0, fmt.Errorf("int8类型转换，整数 %d 超出范围 [%d, %d]", val, math.MinInt8, math.MaxInt8)
		}
		return int8(val), nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		val := v.Uint()
		if val > uint64(math.MaxInt8) {
			return 0, fmt.Errorf("int8类型转换，无符号整数 %d 超出范围 [0, %d]", val, math.MaxInt8)
		}
		return int8(val), nil
	case reflect.Float32, reflect.Float64:
		val := v.Float()
		if val < float64(math.MinInt8) || val > float64(math.MaxInt8) {
			return 0, fmt.Errorf("int8类型转换，浮点数 %f 超出范围 [%d, %d]", val, math.MinInt8, math.MaxInt8)
		}
		return int8(val), nil
	case reflect.String:
		num, err := strconv.ParseInt(v.String(), 10, 64)
		if err != nil {
			return 0, fmt.Errorf("int8类型转换，字符串 '%s' 解析失败: %w", v.String(), err)
		}
		if num < math.MinInt8 || num > math.MaxInt8 {
			return 0, fmt.Errorf("int8类型转换，字符串数值 %d 超出范围 [%d, %d]", num, math.MinInt8, math.MaxInt8)
		}
		return int8(num), nil
	case reflect.Bool:
		if v.Bool() {
			return 1, nil
		}
		return 0, nil
	default:
		return 0, fmt.Errorf("int8类型转换，不支持类型: %T", value)
	}
}

// 将不同类型的值转换为 int16 类型
func ToInt16(value interface{}) (int16, error) {
	v := reflect.ValueOf(value)
	if !v.IsValid() {
		return 0, nil
	}

	switch v.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		val := v.Int()
		if val < math.MinInt16 || val > math.MaxInt16 {
			return 0, fmt.Errorf("int16类型转换，整数 %d 超出范围 [%d, %d]", val, math.MinInt16, math.MaxInt16)
		}
		return int16(val), nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		val := v.Uint()
		if val > uint64(math.MaxInt16) {
			return 0, fmt.Errorf("int16类型转换，无符号整数 %d 超出范围 [0, %d]", val, math.MaxInt16)
		}
		return int16(val), nil
	case reflect.Float32, reflect.Float64:
		val := v.Float()
		if val < float64(math.MinInt16) || val > float64(math.MaxInt16) {
			return 0, fmt.Errorf("int16类型转换，浮点数 %f 超出范围 [%d, %d]", val, math.MinInt16, math.MaxInt16)
		}
		return int16(val), nil
	case reflect.String:
		num, err := strconv.ParseInt(v.String(), 10, 64)
		if err != nil {
			return 0, fmt.Errorf("int16类型转换，字符串 '%s' 解析失败: %w", v.String(), err)
		}
		if num < math.MinInt16 || num > math.MaxInt16 {
			return 0, fmt.Errorf("int16类型转换，字符串数值 %d 超出范围 [%d, %d]", num, math.MinInt16, math.MaxInt16)
		}
		return int16(num), nil
	case reflect.Bool:
		if v.Bool() {
			return 1, nil
		}
		return 0, nil
	default:
		return 0, fmt.Errorf("int16类型转换，不支持类型: %T", value)
	}
}

// 将不同类型的值转换为 int32 类型
func ToInt32(value interface{}) (int32, error) {
	v := reflect.ValueOf(value)
	if !v.IsValid() {
		return 0, nil
	}

	switch v.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		val := v.Int()
		// 检查是否在int32范围内
		if val < math.MinInt32 || val > math.MaxInt32 {
			return 0, fmt.Errorf("int32类型转换，整数 %d 超出范围 [%d, %d]", val, math.MinInt32, math.MaxInt32)
		}
		return int32(val), nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		val := v.Uint()
		// 检查无符号整数转换为int32是否超出范围
		if val > uint64(math.MaxInt32) {
			return 0, fmt.Errorf("int32类型转换，无符号整数 %d 超出范围 [0, %d]", val, math.MaxInt32)
		}
		return int32(val), nil
	case reflect.Float32, reflect.Float64:
		val := v.Float()
		// 检查浮点数转换为int32是否超出范围
		if val < float64(math.MinInt32) || val > float64(math.MaxInt32) {
			return 0, fmt.Errorf("int32类型转换，浮点数 %f 超出范围 [%d, %d]", val, math.MinInt32, math.MaxInt32)
		}
		// 截断小数部分
		return int32(val), nil
	case reflect.String:
		// 先解析为int64，再检查范围
		num, err := strconv.ParseInt(v.String(), 10, 64)
		if err != nil {
			return 0, fmt.Errorf("int32类型转换，字符串 '%s' 解析失败: %w", v.String(), err)
		}
		if num < math.MinInt32 || num > math.MaxInt32 {
			return 0, fmt.Errorf("int32类型转换，字符串数值 %d 超出范围 [%d, %d]", num, math.MinInt32, math.MaxInt32)
		}
		return int32(num), nil
	case reflect.Bool:
		if v.Bool() {
			return 1, nil
		}
		return 0, nil
	default:
		return 0, fmt.Errorf("int32类型转换，不支持类型: %T", value)
	}
}

// 将不同类型的值转换为 int 类型
func ToInt(value interface{}) (int, error) {
	v := reflect.ValueOf(value)
	if !v.IsValid() {
		return 0, nil
	}
	switch v.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return int(v.Int()), nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return int(v.Uint()), nil
	case reflect.Float32, reflect.Float64:
		return int(v.Float()), nil
	case reflect.String:
		return strconv.Atoi(v.String())
	case reflect.Bool:
		if v.Bool() {
			return 1, nil
		}
		return 0, nil
	default:
		return 0, fmt.Errorf("int类型转换，不支持类型: %T", value)
	}
}

// 将不同类型的值转换为 int64 类型
func ToInt64(value interface{}) (int64, error) {
	v := reflect.ValueOf(value)
	if !v.IsValid() {
		return 0, nil
	}

	switch v.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return v.Int(), nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		// 注意：无符号整数转换为有符号整数时可能会导致值变化
		return int64(v.Uint()), nil
	case reflect.Float32, reflect.Float64:
		// 注意：浮点数转换为整数会截断小数部分
		return int64(v.Float()), nil
	case reflect.String:
		return strconv.ParseInt(v.String(), 10, 64)
	case reflect.Bool:
		if v.Bool() {
			return 1, nil
		}
		return 0, nil
	default:
		return 0, fmt.Errorf("int64类型转换，不支持类型: %T", value)
	}
}

// 严格转换为 uint8，拒绝非零小数位（整数或整数型字符串）
func ToUint8(value interface{}) (uint8, error) {
	errPrefix := "uint8类型转换"
	v := reflect.ValueOf(value)
	if !v.IsValid() {
		return 0, nil
	}
	switch v.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		val := v.Int()
		if val < 0 || val > math.MaxUint8 {
			return 0, fmt.Errorf("%s，整数 %d 超出 uint8 范围 [0, 255]", errPrefix, val)
		}
		return uint8(val), nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		val := v.Uint()
		if val > math.MaxUint8 {
			return 0, fmt.Errorf("%s，无符号整数 %d 超出范围", errPrefix, val)
		}
		return uint8(val), nil
	case reflect.Float32, reflect.Float64:
		val := v.Float()
		if val != math.Trunc(val) { // 检查小数位是否为 0
			return 0, fmt.Errorf("%s，浮点数 %f 包含非零小数位", errPrefix, val)
		}
		valInt := int(val)
		if valInt < 0 || valInt > math.MaxUint8 {
			return 0, fmt.Errorf("%s，浮点数 %f 超出范围", errPrefix, val)
		}
		return uint8(valInt), nil
	case reflect.String:
		val := v.String()
		s := strings.TrimSpace(val)
		// 处理包含全是 0 的小数位的情况
		if strings.Contains(s, ".") {
			parts := strings.Split(s, ".")
			if len(parts) == 2 && strings.TrimLeft(parts[1], "0") == "" {
				s = parts[0]
			} else {
				return 0, fmt.Errorf("%s，字符串 '%s' 包含非零小数位", errPrefix, s)
			}
		}
		if strings.ContainsAny(s, "eE") {
			return 0, fmt.Errorf("%s，字符串 '%s' 包含指数", errPrefix, s)
		}
		num, err := strconv.ParseUint(s, 10, 8)
		if err != nil {
			return 0, fmt.Errorf("%s，字符串 '%s' 非有效整数: %w", errPrefix, s, err)
		}
		return uint8(num), nil
	case reflect.Bool:
		if v.Bool() {
			return 1, nil
		}
		return 0, nil
	default:
		return 0, fmt.Errorf("%s，不支持类型: %T", errPrefix, value)
	}
}

// 严格转换为 uint16，拒绝非零小数位（整数或整数型字符串）
func ToUint16(value interface{}) (uint16, error) {
	errPrefix := "uint16类型转换"
	v := reflect.ValueOf(value)
	if !v.IsValid() {
		return 0, nil
	}
	switch v.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		val := v.Int()
		if val < 0 || val > math.MaxUint16 {
			return 0, fmt.Errorf("%s，整数 %d 超出 uint16 范围 [0, 65535]", errPrefix, val)
		}
		return uint16(val), nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		val := v.Uint()
		if val > math.MaxUint16 {
			return 0, fmt.Errorf("%s，无符号整数 %d 超出范围", errPrefix, val)
		}
		return uint16(val), nil
	case reflect.Float32, reflect.Float64:
		val := v.Float()
		if val != math.Trunc(val) { // 检查小数位是否为 0
			return 0, fmt.Errorf("%s，浮点数 %f 包含非零小数位", errPrefix, val)
		}
		valInt := int(val)
		if valInt < 0 || valInt > math.MaxUint16 {
			return 0, fmt.Errorf("%s，浮点数 %f 超出范围", errPrefix, val)
		}
		return uint16(valInt), nil
	case reflect.String:
		val := v.String()
		s := strings.TrimSpace(val)
		// 处理包含全是 0 的小数位的情况
		if strings.Contains(s, ".") {
			parts := strings.Split(s, ".")
			if len(parts) == 2 && strings.TrimLeft(parts[1], "0") == "" {
				s = parts[0]
			} else {
				return 0, fmt.Errorf("%s，字符串 '%s' 包含非零小数位", errPrefix, s)
			}
		}
		if strings.ContainsAny(s, "eE") {
			return 0, fmt.Errorf("%s，字符串 '%s' 包含指数", errPrefix, s)
		}
		num, err := strconv.ParseUint(s, 10, 16)
		if err != nil {
			return 0, fmt.Errorf("%s，字符串 '%s' 非有效整数: %w", errPrefix, s, err)
		}
		return uint16(num), nil
	case reflect.Bool:
		if v.Bool() {
			return 1, nil
		}
		return 0, nil
	default:
		return 0, fmt.Errorf("%s，不支持类型: %T", errPrefix, value)
	}
}

// 严格转换为 uint32，拒绝非零小数位（整数或整数型字符串）
func ToUint32(value interface{}) (uint32, error) {
	errPrefix := "uint32类型转换"
	v := reflect.ValueOf(value)
	if !v.IsValid() {
		return 0, nil
	}
	switch v.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		val := v.Int()
		if val < 0 || val > math.MaxUint32 {
			return 0, fmt.Errorf("%s，整数 %d 超出 uint32 范围 [0, 4294967295]", errPrefix, val)
		}
		return uint32(val), nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		val := v.Uint()
		if val > math.MaxUint32 {
			return 0, fmt.Errorf("%s，无符号整数 %d 超出范围", errPrefix, val)
		}
		return uint32(val), nil
	case reflect.Float32, reflect.Float64:
		val := v.Float()
		if val != math.Trunc(val) { // 检查小数位是否为 0
			return 0, fmt.Errorf("%s，浮点数 %f 包含非零小数位", errPrefix, val)
		}
		valInt := int(val)
		if valInt < 0 || valInt > math.MaxUint32 {
			return 0, fmt.Errorf("%s，浮点数 %f 超出范围", errPrefix, val)
		}
		return uint32(valInt), nil
	case reflect.String:
		val := v.String()
		s := strings.TrimSpace(val)
		// 处理包含全是 0 的小数位的情况
		if strings.Contains(s, ".") {
			parts := strings.Split(s, ".")
			if len(parts) == 2 && strings.TrimLeft(parts[1], "0") == "" {
				s = parts[0]
			} else {
				return 0, fmt.Errorf("%s，字符串 '%s' 包含非零小数位", errPrefix, s)
			}
		}
		if strings.ContainsAny(s, "eE") {
			return 0, fmt.Errorf("%s，字符串 '%s' 包含指数", errPrefix, s)
		}
		num, err := strconv.ParseUint(s, 10, 32)
		if err != nil {
			return 0, fmt.Errorf("%s，字符串 '%s' 非有效整数: %w", errPrefix, s, err)
		}
		return uint32(num), nil
	case reflect.Bool:
		if v.Bool() {
			return 1, nil
		}
		return 0, nil
	default:
		return 0, fmt.Errorf("%s，不支持类型: %T", errPrefix, value)
	}
}

// 严格转换为 uint64，拒绝非零小数位（整数或整数型字符串）
func ToUint64(value interface{}) (uint64, error) {
	errPrefix := "uint64类型转换"
	v := reflect.ValueOf(value)
	if !v.IsValid() {
		return 0, nil
	}
	switch v.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		val := v.Int()
		if val < 0 {
			return 0, fmt.Errorf("%s，整数 %d 超出 uint64 范围", errPrefix, val)
		}
		return uint64(val), nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return v.Uint(), nil
	case reflect.Float32, reflect.Float64:
		val := v.Float()
		if val != math.Trunc(val) { // 检查小数位是否为 0
			return 0, fmt.Errorf("%s，浮点数 %f 包含非零小数位", errPrefix, val)
		}
		if val < 0 {
			return 0, fmt.Errorf("%s，浮点数 %f 为负数，超出 uint64 范围", errPrefix, val)
		}
		return uint64(val), nil
	case reflect.String:
		val := v.String()
		s := strings.TrimSpace(val)
		// 处理包含全是 0 的小数位的情况
		if strings.Contains(s, ".") {
			parts := strings.Split(s, ".")
			if len(parts) == 2 && strings.TrimLeft(parts[1], "0") == "" {
				s = parts[0]
			} else {
				return 0, fmt.Errorf("%s，字符串 '%s' 包含非零小数位", errPrefix, s)
			}
		}
		if strings.ContainsAny(s, "eE") {
			return 0, fmt.Errorf("%s，字符串 '%s' 包含指数", errPrefix, s)
		}
		num, err := strconv.ParseUint(s, 10, 64)
		if err != nil {
			return 0, fmt.Errorf("%s，字符串 '%s' 非有效整数: %w", errPrefix, s, err)
		}
		return num, nil
	case reflect.Bool:
		if v.Bool() {
			return 1, nil
		}
		return 0, nil
	default:
		return 0, fmt.Errorf("%s，不支持类型: %T", errPrefix, value)
	}
}

// float64转int
func Float64ToInts(v any) any {
	// 进行类型断言，判断输入是否为 float64 类型
	if f, ok := v.(float64); ok {
		// 判断是否有小数部分
		if math.Floor(f) != f {
			return f
		}
		if f >= -128 && f <= 127 {
			return int8(f)
		}
		if f >= -32768 && f <= 32767 {
			return int16(f)
		}
		if f >= -2147483648 && f <= 2147483647 {
			return int16(32)
		}
		if f >= -9223372036854775808 && f <= 9223372036854775807 {
			return int16(64)
		}
	} else if sliceValue, ok := v.([]any); ok {
		for i, vv := range sliceValue {
			sliceValue[i] = Float64ToInts(vv)
		}
		v = sliceValue
	} else if mapValue, ok := v.(map[string]any); ok {
		v = MapFloat64ToInts(mapValue)
	}
	return v
}

// map中的float64转int
func MapFloat64ToInts(params map[string]any) map[string]any {
	for key, value := range params {
		params[key] = Float64ToInts(value)
	}
	return params
}

// float64转uint
func Float64ToUints(v any) any {
	// 进行类型断言，判断输入是否为 float64 类型
	f, ok := v.(float64)
	if ok {
		// 判断是否有小数部分
		if math.Floor(f) != f {
			return f
		}
		if f >= 0 && f <= 255 {
			return uint8(f)
		}
		if f >= 0 && f <= 65535 {
			return uint16(f)
		}
		if f >= 0 && f <= 4294967295 {
			return uint32(f)
		}
		if f >= 0 && f <= 18446744073709551615 {
			return uint64(f)
		}
	} else if sliceValue, ok := v.([]any); ok {
		for i, vv := range sliceValue {
			sliceValue[i] = Float64ToUints(vv)
		}
		v = sliceValue
	} else if mapValue, ok := v.(map[string]any); ok {
		v = MapFloat64ToUints(mapValue)
	}
	return v
}

// map中的float64转uint
func MapFloat64ToUints(params map[string]any) map[string]any {
	for key, value := range params {
		params[key] = Float64ToUints(value)
		// fmt.Printf("%v:%v|%T|%v|%T\r\n", key, value, value, params[key], params[key])
	}
	return params
}
